#include "stdafx.h"
#include "PropertyEditor.h"
#include "NaturalSplinePropertyEditor.h"
#include "..\NaturalSplineEditor.h"
#include "core/Math/intersection.h"

namespace SEPEditor
{
#define NODE_SPRITE_SIZE 10
	bool NaturalSplinePropertyEditor::mouse_down(System::Windows::Forms::MouseEventArgs^ e, RenderView^ rv)
	{
		editable=false;

		natural_spline_t* pospath=editor->obj->obj;
		editor->obj->entity->set_editor_param(&pospath,"pospath",NULL);


		float4x4 mtxtrf;
		mtxtrf.identity();
		char nam[1024];
		String_to_string(editor->prop_name,nam);
		editor->obj->entity->set_editor_param(&mtxtrf,"mtxtrf",nam);

		mx=e->X;
		my=e->Y;
//		float2 sp=rv->get_screenpos(e);

		float4x4 viewprojmtx; 
		rv->get_viewprojection_mtx(viewprojmtx);

		bool van=false;
		float mint=FLT_MAX;
		int index;
		for (int n=0; n<editor->obj->get_node_num(); ++n)
		{
			float ttt=editor->obj->get_time(n);
			float3 act_pos=mul4x3(pospath->get_pos(ttt),mtxtrf);
			float4 ap(act_pos,1);
			ap=mul(ap,viewprojmtx);
			ap/=ap.w;
			if (ap.z<0 || ap.z>1) continue;

			float x=(ap.x+1)*rv->getRenderPanel()->Width/2;
			float y=(1-ap.y)*rv->getRenderPanel()->Height/2;

			float d2=sqr(mx-x)+sqr(my-y);

//			float d2=sqr(ap.x-sp.x)*sqr(rv->getRenderPanel()->Width)+sqr(ap.y-sp.y)*sqr(rv->getRenderPanel()->Height);

			if (d2<NODE_SPRITE_SIZE*NODE_SPRITE_SIZE/2)
			{
				index=n;
				van=true;
				break;
			}
		}

		bool b=false;

		if (van)
		{
			editor->set_selected(index);
			if (e->Button==System::Windows::Forms::MouseButtons::Right && index!=0 && editor->obj->get_node_num()!=2)
			{
				if (MessageBox::Show(
					"Spline node will be deleted!", 
					"SEP Editor", MessageBoxButtons::YesNo, 
					MessageBoxIcon::Exclamation)==System::Windows::Forms::DialogResult::Yes)
					editor->delete_node(index);
			}
			b=true;

			editable=true;

		}
		else
		{
			if (e->Button==System::Windows::Forms::MouseButtons::Left && Control::ModifierKeys==Keys::Control)//add node
			{

				float maxt=editor->obj->get_time(editor->obj->get_node_num()-1);
				int minindex=-1;
				float mindist=FLT_MAX;
				float w2=(float)rv->getRenderPanel()->Width/2;
				float h2=(float)rv->getRenderPanel()->Height/2;

				for (int n=0; n<editor->obj->get_node_num()-1; ++n)
				{
					float tmin=editor->obj->get_time(n);
					float tmax=editor->obj->get_time(n+1);
					float step=(tmax-tmin)/10;

					for (float t=tmin; t<tmax; t+=step)
					{
						float3 act_pos=mul4x3(pospath->get_pos(t),mtxtrf);

						float4 ap(act_pos,1);
						ap=mul(ap,viewprojmtx);
						ap/=ap.w;
						if (ap.z>0 && ap.z<1)
						{
							float x=(ap.x+1)*w2;
							float y=(1-ap.y)*h2;

							float d2=sqr(mx-x)+sqr(my-y);

							if (d2<mindist)
							{
								mindist=d2;
								minindex=n;
//								break;
							}
						}
					}
				}

				if (minindex!=-1)
				{
					float tmin=editor->obj->get_time(minindex);
					float tmax=editor->obj->get_time(minindex+1);
					float step=(tmax-tmin)/1000;

					float minmintime=-1;
					float minmindist=FLT_MAX;

					for (float t=tmin; t<tmax; t+=step)
					{
						float3 act_pos=mul4x3(pospath->get_pos(t),mtxtrf);

						float4 ap(act_pos,1);
						ap=mul(ap,viewprojmtx);
						ap/=ap.w;
						if (ap.z>0 && ap.z<1)
						{
							float x=(ap.x+1)*w2;
							float y=(1-ap.y)*h2;

							float d2=sqr(mx-x)+sqr(my-y);

							if (d2<NODE_SPRITE_SIZE*NODE_SPRITE_SIZE/8)
							{
								if (d2<minmindist)
								{
									minmindist=d2;
									minmintime=t;
								}
							}
						}
					}

					if (minmintime!=-1)
					{
						editor->add_node(minmintime);
						editable=true;
						b=true;
					}
				}
			}
		}
		return b;
	}
	bool NaturalSplinePropertyEditor::mouse_up(System::Windows::Forms::MouseEventArgs^ e, RenderView^ rv)
	{
		return true;
	}
	bool NaturalSplinePropertyEditor::mouse_move(System::Windows::Forms::MouseEventArgs^ e, RenderView^ rv)
	{
		if (!editable)
			return false;
		bool b=false;
		if (e->Button==System::Windows::Forms::MouseButtons::Middle)//move node
		{
			if (editor->obj->get_selected_index()==-1)
				return false;

			float4x4 mtxtrf;
			mtxtrf.identity();
			editor->obj->entity->set_editor_param(&mtxtrf,"mtxtrf",NULL);
			float4x4 imtxtrf; imtxtrf.invert(mtxtrf);

			float3 obj_pos=mul4x3(editor->obj->get_pos(editor->obj->get_selected_index()),mtxtrf);
			float3 tr=rv->get_translate(obj_pos,e->X,e->Y,mx,my);
			editor->set_pos(mul4x3(obj_pos+tr,imtxtrf));
			b=true;
		}
		else if (e->Button==System::Windows::Forms::MouseButtons::Left) //rotate node
		{
#define ROTSPEED DEGREE_TO_RADIAN*(3)
			float3 axis;
			float angle;
			float w=(float)rv->getRenderPanel()->Width;
			float h=(float)rv->getRenderPanel()->Height;
			if (rv->params->view_mode>=view_top)
			{
				axis=rv->params->camera_matrix.axis(2);

				float x=(e->X-w/2);
				float y=-(e->Y-h/2);
				float xp=(mx-w/2);
				float yp=-(my-h/2);

				float dx=x-xp;
				angle=dx*ROTSPEED;
			}
			else if (rv->params->view_mode==view_perspective)
			{
				float x=(e->X-w/2);
				float y=-(e->Y-h/2);
				float xp=(mx-w/2);
				float yp=-(my-h/2);

				float dx=x-xp;
				float dy=y-yp;

				if (fabsf(dx)>fabsf(dy))//vizszintes mozgatas a nagyobb, forgatas a fuggoleses tengely korul
				{
					axis.set(0,1,0);
					angle=-dx*ROTSPEED;
				}
				else//forgatas a vizszintes kameratengely korul
				{
					axis=rv->params->camera_matrix.axis(0);
					angle=dy*ROTSPEED;
				}
			}
			float4x4 mtxtrf;
			mtxtrf.identity();
			editor->obj->entity->set_editor_param(&mtxtrf,"mtxtrf",NULL);
			float4x4 imtxtrf; imtxtrf.invert(mtxtrf);

			float3 obj_rot=editor->obj->get_rot(editor->obj->get_selected_index());
			float4x4 m; m.identity(); m.from_rotation(DEGREE_TO_RADIAN*obj_rot.x,DEGREE_TO_RADIAN*obj_rot.y,DEGREE_TO_RADIAN*obj_rot.z);
			float4x4 ma; ma.mul(m,mtxtrf);
			ma.rotate(axis,angle);
			float4x4 m2;
			m2.mul(ma,imtxtrf);
			float y,p,r;
			m2.to_rotation(y,p,r);
			y*=RADIAN_TO_DEGREE;
			p*=RADIAN_TO_DEGREE;
			r*=RADIAN_TO_DEGREE;
			while (obj_rot.x-y>90)
				y+=360;
			while (y-obj_rot.x>90)
				y-=360;
			obj_rot.x=y;
			while (obj_rot.y-p>90)
				p+=360;
			while (p-obj_rot.y>90)
				p-=360;
			obj_rot.y=p;
			while (obj_rot.z-r>90)
				r+=360;
			while (r-obj_rot.z>90)
				r-=360;
			obj_rot.z=r;
			editor->set_rot(obj_rot);
//			m.from_rotation(obj_rot.x,obj_rot.y,obj_rot.z);
			b=true;
		}
		mx=e->X;
		my=e->Y;
		return b;
	}
}